Skip to content

Make ranges jump address space gaps - #618

Open
mkroening wants to merge 5 commits into
rust-osdev:masterfrom
mkroening:range-jump-gap
Open

mkroening wants to merge 5 commits into
rust-osdev:masterfrom
mkroening:range-jump-gap

Conversation

@mkroening

Copy link
Copy Markdown
Member

I recently discovered that this range panics during iteration, even though it does not even cross the address space gap:

let pages = PageRangeInclusive {
	start: Page::<Size4KiB>::from_start_address(VirtAddr::new(0x0000_7fff_ffff_f000))
		.unwrap(),
	end: Page::<Size4KiB>::from_start_address(VirtAddr::new(0x0000_7fff_ffff_f000))
		.unwrap(),
};

We could use #616 to fix that, similar to #617. I believe it makes more sense to jump the gap, as proposed in #589 and already done via the unstable Step trait.

@Freax13 Freax13 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution!

Page::range(start, end).into_iter().next();
}

// TODO: This probably shouldn't panic, but we can't fix this without a breaking change.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add this behavior change as a breaking change to the release notes.

Comment thread src/structures/paging/page.rs Outdated

#[test]
#[should_panic = "attempt to add with overflow or resulted in non-canonical virtual address"]
fn test_page_range_next_jumping_gap_panics() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests should be renamed.

Comment on lines +837 to +840
assert_eq!(
Page::range_inclusive(start, end).into_iter().next(),
Some(start)
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add similar asserts to the remaining tests that formerly panicked.

Comment on lines +220 to +228
// FIXME: Move this into the `Step` impl, once `Step` is stabilized.
pub(crate) fn backward_checked_impl(start: Self, count: usize) -> Option<Self> {
let count = u64::try_from(count).ok()?.checked_mul(S::SIZE)?;
let start_address = VirtAddr::backward_checked_u64(start.start_address, count)?;
Some(Self {
start_address,
size: PhantomData,
})
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's replace the implementation of backward_checked for Page's Step with a call to this function.

Comment on lines 672 to 679
// If the start of the inclusive range is 0, decrementing end until
// it is smaller than the start will cause an integer underflow.
// So instead, in that case we increment start rather than decrementing end.
if self.0.end.start_address().as_u64() != 0 {
self.0.end -= 1;
self.0.end = Page::backward_checked_impl(self.0.end, 1)?;
} else {
self.0.start += 1;
self.0.start = Page::forward_checked_impl(self.0.start, 1)?;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do this:

            // If the start of the inclusive range is 0, decrementing end until
            // it is smaller than the start will cause an integer underflow.
            // In that case we increment start rather than decrementing end.
            if let Some(end) = Page::backward_checked_impl(self.0.end, 1) {
                self.0.end = end;
            } else {
                self.0.start = self.0.start + 1;
            }

Comment thread src/structures/paging/page.rs Outdated
Comment on lines +862 to +869
assert_eq!(
Page::range_inclusive(start, end).into_iter().next(),
Some(start)
);
assert_eq!(
Page::range_inclusive(start, end).into_iter().next(),
Some(start)
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a small issue in the original code: We called Page::range_inclusive(start, end).into_iter().next(); twice with the same inputs. We don't need to do this twice.

Note that this does not add a checked version for subtracting two addresses yet.
Note that this changes the panic behavior, since `rhs * S::SIZE` did not panic before without overflow checks.
Note that this does not add a checked version for subtracting two pages or frames yet.
@mkroening

Copy link
Copy Markdown
Member Author

Thanks for the review! All comments should be addressed. :)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants